/**
 *
 */
package com.angel.annotation.managers;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.util.HashMap;
import java.util.Map;

import com.angel.annotation.exceptions.AnnotationManagerException;
import com.angel.annotation.interfaces.AnnotationAction;
import com.angel.common.helpers.ReflectionHelper;

/**
 * @author William
 *
 */
public class AnnotationManagerLocator {

	private static Map<String, AnnotationManager> ANNOTATION_MANAGERS = new HashMap<String, AnnotationManager>();

	private AnnotationManagerLocator(){
		super();
	}

	public static AnnotationManager find(Class<? extends Annotation> annotationClass){
		AnnotationManager annotationManager = null;
		for(AnnotationManager am : ANNOTATION_MANAGERS.values()){
			if(annotationManager == null && am.getClassAnnotation().equals(annotationClass)){
				annotationManager = am;
			}
		}
		return annotationManager;
	}

	public static Boolean isLocated(Class<? extends AnnotationManager> classAnnotationManager){
		return ANNOTATION_MANAGERS.containsValue(classAnnotationManager);
	}

	public synchronized static AnnotationManager locate(Class<? extends AnnotationManager> classAnnotationManager){
		return locate(classAnnotationManager, new HashMap<ElementType, AnnotationAction>());
	}

	@SuppressWarnings("unchecked")
	public synchronized static AnnotationManager locate(Class<? extends AnnotationManager> classAnnotationManager, Map<ElementType,? extends AnnotationAction> annotationActions){
		if(containsAnnotationManager(classAnnotationManager)){
			return ANNOTATION_MANAGERS.get(classAnnotationManager.getName());
		} else {
			AnnotationManager annotationManager = (AnnotationManager) ReflectionHelper.createObject(classAnnotationManager);
			if(annotationManager != null){
				annotationManager.addAllTargetActions((Map<ElementType, AnnotationAction>) annotationActions);
				ANNOTATION_MANAGERS.put(classAnnotationManager.getName(),annotationManager);
				return ANNOTATION_MANAGERS.get(classAnnotationManager.getName());
			} else {
				throw new AnnotationManagerException("Could create annotation manager instance for class [" + classAnnotationManager.getName() + "].");
			}
		}
	}

	private static Boolean containsAnnotationManager(Class<? extends AnnotationManager> classAnnotationManager){
		return ANNOTATION_MANAGERS.get(classAnnotationManager.getName()) != null;
	}
}
